---
id: createSelector
title: createSelector
sidebar_label: createSelector
hide_title: true
---

&nbsp;

# `createSelector`

## Overview

The `createSelector` utility from the [Reselect library](https://github.com/reduxjs/reselect), re-exported for ease of use.

For more details on using `createSelector`, see:

- The [Reselect API documentation](https://github.com/reduxjs/reselect)
- [React-Redux docs: Hooks API - Using memoizing selectors](https://react-redux.js.org/next/api/hooks#using-memoizing-selectors)
- [Idiomatic Redux: Using Reselect Selectors for Encapsulation and Performance](https://blog.isquaredsoftware.com/2017/12/idiomatic-redux-using-reselect-selectors/)
- [React/Redux Links: Reducers and Selectors](https://github.com/markerikson/react-redux-links/blob/master/redux-reducers-selectors.md)

:::note
Prior to v0.7, RTK re-exported `createSelector` from [`selectorator`](https://github.com/planttheidea/selectorator), which
allowed using string keypaths as input selectors. This was removed, as it ultimately did not provide enough benefits, and
the string keypaths made static typing for selectors difficult.
:::

## `createDraftSafeSelector`

In general, we recommend against using selectors inside of reducers:

- Selectors typically expect the entire Redux state object as an argument, while slice reducers only have access to a specific subset of the entire Redux state
- Reselect's `createSelector` relies on reference comparisons to determine if inputs have changed, and if an Immer Proxy-wrapped draft value is passed in to a selector, the selector may see the same reference and think nothing has changed.

However, some users have requested the ability to create selectors that will work correctly inside of Immer-powered reducers. One use case for this might be collecting an ordered set of items when using `createEntityAdapter`, such as `const orderedTodos = todosSelectors.selectAll(todosState)`, and then using `orderedTodos` in the rest of the reducer logic.

Besides re-exporting `createSelector`, RTK also exports a wrapped version of `createSelector` named `createDraftSafeSelector` that allows you to create selectors that can safely be used inside of `createReducer` and `createSlice` reducers with Immer-powered mutable logic. When used with plain state values, the selector will still memoize normally based on the inputs. But, when used with Immer draft values, the selector will err on the side of recalculating the results, just to be safe.

All selectors created by `entityAdapter.getSelectors` are "draft safe" selectors by default.

Example:

```ts no-transpile
const selectSelf = (state: State) => state
const unsafeSelector = createSelector(selectSelf, (state) => state.value)
const draftSafeSelector = createDraftSafeSelector(
  selectSelf,
  (state) => state.value,
)

// in your reducer:

state.value = 1

const unsafe1 = unsafeSelector(state)
const safe1 = draftSafeSelector(state)

state.value = 2

const unsafe2 = unsafeSelector(state)
const safe2 = draftSafeSelector(state)
```

After executing that, `unsafe1` and `unsafe2` will be of the same value, because the memoized selector was
executed on the same object - but `safe2` will actually be different from `safe1` (with the updated value of `2`),
because the safe selector detected that it was executed on a Immer draft object and recalculated using the current
value instead of returning a cached value.

:::tip `createDraftSafeSelectorCreator`

RTK also exports a `createDraftSafeSelectorCreator` function, the "draft safe" equivalent of [`createSelectorCreator`](https://github.com/reduxjs/reselect#createselectorcreatormemoize-memoizeoptions).

```ts no-transpile
import {
  createDraftSafeSelectorCreator,
  weakMapMemoize,
} from '@reduxjs/toolkit'

const createWeakMapDraftSafeSelector =
  createDraftSafeSelectorCreator(weakMapMemoize)

const selectSelf = (state: State) => state
const draftSafeSelector = createWeakMapDraftSafeSelector(
  selectSelf,
  (state) => state.value,
)
```

:::

### Defining a Pre-Typed `createDraftSelector`

As of RTK 2.1, you can define a "pre-typed" version of `createDraftSafeSelector` that can have the type for `state` built in. This lets you set up those types once, so you don't have to repeat them each time you call `createDraftSafeSelector`.

```ts no-transpile
const createTypedDraftSafeSelector =
  createDraftSafeSelector.withTypes<RootState>()
```

Import and use the pre-typed `createTypedDraftSafeSelector` function, and it will automatically know that the `state` argument is of type `RootState`.

:::warning Known Limitations
Currently this approach only works if input selectors are provided as a single array.

If you pass the input selectors as separate inline arguments, the parameter types of the result function will not be inferred. As a workaround you can either

1. Wrap your input selectors in a single array
2. You can annotate the parameter types of the result function:

```ts no-transpile
import { createSelector } from 'reselect'

interface Todo {
  id: number
  completed: boolean
}

interface Alert {
  id: number
  read: boolean
}

export interface RootState {
  todos: Todo[]
  alerts: Alert[]
}

export const createTypedDraftSafeSelector =
  createDraftSafeSelector.withTypes<RootState>()

const selectTodoIds = createTypedDraftSafeSelector(
  // Type of `state` is set to `RootState`, no need to manually set the type
  (state) => state.todos,
  // ❌ Known limitation: Parameter types are not inferred in this scenario
  // so you will have to manually annotate them.
  (todos: Todo[]) => todos.map(({ id }) => id),
)
```
